#!/usr/bin/env python
# coding=UTF-8
import random
import logging
import json
import time
import datetime
import copy
import urllib

import redisco
from redisco.containers import List, Hash

from tools import nsq_pub, json_encode
import dao

def get_last_data(reader, bid, uid, data):
    uid = str(uid)
    user_info = Hash("%s_%s" % (bid, uid))
    rid = user_info['rid']
    if not rid:
        rid = data.get("rid", "")
    room = Hash("r:%s" % rid)
    tdh = KABao(rid, bid)
    last_put_user = tdh.room['last_put_user']
    last_put_card = tdh.room['last_put_card']
    if not last_put_card:
        last_put_card = []
    else:
        last_put_card = last_put_card.split(",")
    all_player_data = []
    db = dao.Game_DB()
    members = tdh.members
    for member in members:
        if member:
            p = Player(member, bid, rid)
            player_data = p.get_data()
            player_info = db.get_player(rid, uid)
            player_data['status'] = player_info['status']
            player_data['user_score'] = player_info['score']
            player_data['online'] = player_info['online']
            if member == uid:
                player_data['current_card'] = sorted(player_data['current_card'], key=lambda x:int(x), reverse=True)
                player_data['left_num'] = len(player_data['current_card'])
                
            else:
                player_data['left_num'] = len(player_data['current_card'])
                player_data['current_card'] = []
            all_player_data.append(player_data)
        
    dealer = tdh.room['dealer']
    if not dealer:
        dealer = ''
    data = {"act":"get_last_data", 
            "last_put_user":last_put_user, 
            "last_put_card":last_put_card, 
            "game_round":room['game_round'],
            "all_round":room['all_round'],
            "dealer":dealer,
            "all_player_data":all_player_data,
            "rid":rid,
            "status":room['status'],
           }
    
    nsq_pub({"b":bid, "u":uid, "t":"game", "d":data})
    stop_pop_user = tdh.room['stop_pop_user']
    stop_pop_act = tdh.room['stop_pop_act']
    if stop_pop_user:
        if stop_pop_act in ('turn_rob', 'turn_call'):
            nsq_pub({"b":bid, "u":uid, "t":"game", "d":{"act":stop_pop_act, "uid":stop_pop_user, "rid":rid}})
            return
        
        if stop_pop_user == uid:
            my_seat = members.index(uid)
            pre_user = members[my_seat-1]
            tdh.notify_next_user(pre_user)
        else:
            if not last_put_user:
                put_type = "free"
            else:
                put_type = "follow"
            nsq_pub({"b":bid, "u":uid, "t":"game", "d":{"act":"turn_put", "put_type":put_type, "uid":stop_pop_user, "rid":rid, "valid_list":[], "tips_list":[], "last_put_card":last_put_card, "last_put_type":"", "last_put_point":""}})
        
        
class Player():
    def __init__(self, uid, bid='', rid='', first=False):
        self.uid = uid
        self.bid = bid
        self.rid = rid
        if first:
            redisco.connection.delete("p:%s:%s:%s:current_card" % (bid, uid, rid))
            redisco.connection.delete("p:%s:%s:%s:out_card" % (bid, uid, rid))
            #redisco.connection.delete("p:%s:%s:%s:bomb" % (bid, uid, rid))
            #redisco.connection.delete("p:%s:%s:%s:put_num" % (bid, uid, rid))
            redisco.connection.delete("p:%s:%s:%s" % (bid, uid, rid))
            self.score = Hash("p:%s:%s:%s" % (bid, uid, rid))
            self.score['score'] = 0
            self.score['role'] = ''
            self.score['is_dealer'] = ''
        else:
            self.score = Hash("p:%s:%s:%s" % (bid, uid, rid))
        self.current_card = List("p:%s:%s:%s:current_card" % (bid, uid, rid))
        self.out_card = List("p:%s:%s:%s:out_card" % (bid, uid, rid))
        #self.bomb = List("p:%s:%s:%s:bomb" % (bid, uid, rid))
        #self.put_num = List("p:%s:%s:%s:put_num" % (bid, uid, rid))
    
    def clear(self):
        redisco.connection.delete("p:%s:%s:%s:current_card" % (self.bid, self.uid, self.rid))
        redisco.connection.delete("p:%s:%s:%s:out_card" % (self.bid, self.uid, self.rid))
        redisco.connection.delete("p:%s:%s:%s" % (self.bid, self.uid, self.rid))
        
    def get_data(self):
        return {"uid":self.uid,
                "current_card":self.current_card.members,
                "score":self.score['score'],
                "role":self.score['role'],
                "is_dealer":self.score['is_dealer'],
                }

class KABao():
    '''K/A包'''
    def __init__(self, rid, bid, dealer=None):
        self.rid = str(rid)
        if dealer:
            redisco.connection.delete("r:%s:current_card" % rid)
            redisco.connection.delete("r:%s:mid" % rid)
            redisco.connection.delete("r:%s:call_card" % rid)
            self.room = Hash("r:%s" % rid)
            self.room['dealer'] = dealer
            self.room['last_put_user'] = ''
            self.room['stop_pop_user'] = ''
            self.room['stop_pop_act'] = ''
            self.room['call_score'] = '0'
        else:
            self.room = Hash("r:%s" % rid)
        self.current_card = List("r:%s:current_card" % rid)
        self.call_card = List("r:%s:call_card" % rid)
        self.bid = bid
        l = List("r:%s:p" % rid)
        self.members = l.members
    
    def incr_mid(self):
        return redisco.connection.incr("r:%s:mid" % self.rid)
    
    def get_card_point(self, c):
        '''获取某张扑克牌的点数'''
        return int(c)/10
    
    def trans_card(self, card):
        '''转换手牌列表,去掉花色'''
        res = []
        card.sort()
        for c in card:
            card_point = self.get_card_point(c)
            res.append(card_point)
        return res
    
    def is_pair(self, card_list):
        '''对子'''
        if len(card_list) == 2 and len(set(card_list)) == 1:
            return 'pair', len(card_list), card_list[0]
        return False, 0, 0
    
    
    def is_bomb(self, card_list):
        '''炸弹'''
        if len(card_list) >=3 and len(set(card_list)) == 1:
            return 'bomb', len(card_list), card_list[0]
        return False, 0, 0
    
    
    def is_seq(self, card_list):
        '''顺子'''
        if len(card_list) >= 3:
            card_list.sort()
            start_i = card_list[0]
            end_i = card_list[-1]
            if card_list == range(start_i, end_i+1) and end_i < 12:
                return 'seq', len(card_list), start_i
        return False, 0, 0
    
    def is_seq_pair(self, card_list):
        '''连对'''
        res = []
        card_list.sort()
        if len(card_list) >= 4 and len(card_list) % 2 == 0:
            for c in set(card_list):
                if card_list.count(c) != 2:
                    return False, []
                res.append(c)
            res.sort()
            start_i = res[0]
            end_i = res[-1]
            if res == range(start_i, end_i+1) and end_i < 12:
                return 'seq_pair', len(card_list), start_i
        return False, 0, 0
    
    def get_card_type(self, card):
        card_list = self.trans_card(card)
        card_len = len(card_list)
        if card_len >= 3:
            res = self.is_bomb(card_list)
            if res[0]:
                return res
            res = self.is_seq(card_list)
            if res[0]:
                return res
            res = self.is_seq_pair(card_list)
            if res[0]:
                return res
        elif card_len == 2:
            res = self.is_pair(card_list)
            if res[0]:
                return res
        elif card_len == 1:
            return 'single', 1, card_list[0]
        return False, 0, 0
    
    def compare_card(self, card1, card2):
        #判断card2是否比card1牌型大
        card_type2, len2, point2 = self.get_card_type(card2)
        card_type1, len1, point1 = self.get_card_type(card1)
        if card_type1 == card_type2:
            #相同类型的牌
            if card_type1 == 'bomb':
                if len2 > len1:
                    return True
                elif len2 == len1 and point2 > point1:
                    return True
            else:
                if point2 > point1:
                    return True
        elif card_type2 == 'bomb':
            return True
        return False
    
    def get_card_by_point(self, card, card_point):
        res = []
        for c in card:
            if self.get_card_point(c) == card_point:
                res.append(c)
        return res
    
    def get_bomb_card(self, card, bomb_point=0, card_num=3):
        '''取手牌中大于bomb_point的炸弹, 为0则返回所有炸弹'''
        res = []
        tips_list = []
        card_list = self.trans_card(card)
        bomb_list = []
        for c in set(card_list):
            c_cnt = card_list.count(c) 
            if (c_cnt == card_num and c > bomb_point) or c_cnt > card_num:
                bomb_list.append(c)
        for card_point in bomb_list:
            tips_card = self.get_card_by_point(card, card_point)
            res.extend(tips_card)
            tips_list.append(tips_card)
        return res, tips_list

    def get_single_card(self, card, single_point=0):
        '''取手牌中大于single_point点数的单张牌'''
        res = []
        tips_list = []
        card_list = self.trans_card(card)
        for c in set(card_list):
            if c > single_point and card_list.count(c) == 1:
                rs = self.get_card_by_point(card, c)
                res.extend(rs)
                tips_card = rs[:1]
                tips_list.append(tips_card)
        return res, tips_list
    
    def get_pair_card(self, card, pair_point=0):
        '''取手牌中大于pair_point点数的对子扑克牌'''
        res = []
        tips_list = []
        pair_list = []
        card_list = self.trans_card(card)
        for c in set(card_list):
            if card_list.count(c) == 2:
                if c > pair_point:
                    pair_list.append(c)
        for card_point in pair_list:
            tips_card = self.get_card_by_point(card, card_point)
            res.extend(tips_card)
            tips_list.append(tips_card)
        return res, tips_list
    
    def get_seq_card(self, card, seq_s=0, num=3):
        '''获取手牌中包含大于某个点数的顺子对应的扑克牌'''
        seq_list = []
        end_c = 12 - num
        for start_c in range(seq_s+1, end_c+1):
            rs = range(start_c, start_c+num)
            seq_list.append(rs)
        card_list = self.trans_card(card)
        res = []
        tips_list = []
        has_seq_set = set()
        for seq in seq_list:
            if set(seq).issubset(set(card_list)):
                has_seq_set |= set(seq)
                tips_card = []
                for c in seq:
                    rs = self.get_card_by_point(card, c, 1)
                    tips_card.append(rs[0])
                tips_list.append(tips_card)
        has_seq_list = list(has_seq_set)
        for card_point in has_seq_list:
            rs = self.get_card_by_point(card, card_point)
            res.extend(rs)
        return res, tips_list
    
    def get_seq_pair_card(self, card, seq_s=0, num=2):
        '''取手牌中包含大于seq_s的连对'''
        seq_pair_list = []
        end_c = 12 - num
        for start_c in range(seq_s+1, end_c+1):
            rs = range(start_c, start_c+num)
            seq_pair_list.append(rs)
        card_list = self.trans_card(card)
        pair_list = []
        for c in set(card_list):
            if card_list.count(c) >= 2:
                pair_list.append(c)
        res = []
        tips_list = []
        has_seq_set = set()
        for seq in seq_pair_list:
            if set(seq).issubset(set(pair_list)):
                has_seq_set |= set(seq)
                tips_card = []
                for c in seq:
                    rs = self.get_card_by_point(card, c, 2)
                    tips_card.extend(rs)
                tips_list.append(tips_card)
        has_seq_list = list(has_seq_set)
        for card_point in has_seq_list:
            rs = self.get_card_by_point(card, card_point)
            res.extend(rs)
        return res, tips_list
    
    def check_validate(self, card, card_type):
        return self.get_card_type(card)[0] == card_type

    def get_valid_card(self, current_card, last_put_card, last_put_type='', last_put_point=''):
        valid_card = []
        last_put_type, last_card_num, last_put_point = self.get_card_type(last_put_card)
        if last_put_type == 'single':
            valid_card = self.get_single_card(current_card, int(last_put_point))
        elif last_put_type == 'pair':
            valid_card = self.get_pair_card(current_card, int(last_put_point))
        elif last_put_type == 'seq':
            valid_card = self.get_seq_card(current_card, int(last_put_point), last_card_num)
        elif last_put_type == 'seq_pair':
            valid_card = self.get_seq_pair_card(current_card, int(last_put_point), last_card_num)
        if last_put_type == 'bomb':
            valid_card = self.get_bomb_card(current_card, int(last_put_point), last_card_num)
        else:
            bomb_card = self.get_bomb_card(current_card, 0)
            valid_list = bomb_card[0]
            tips_list = bomb_card[1]
            if valid_card:
                valid_card[0].extend(valid_list)
                valid_card[1].extend(tips_list)
            else:
                valid_card = bomb_card
        return valid_card
    
    def crt_deck_card(self):
        all_card = []
        for i in range(10, 140, 10):
                for j in range(1, 5):
                    all_card.append(i+j)
        game_mode = self.room['game_mode']
        del_card = [10, 60, 130]
        #去掉382
        if game_mode == 'k':
            #k包去掉A
            del_card.append(120)
        for i in del_card:
            for j in range(1, 5):
                all_card.remove(i+j)
        random.shuffle(all_card)
        return all_card
    
    def start(self):
        self.room['status'] = 'start'
        game_round = int(self.room['game_round'])
        all_card = self.crt_deck_card()
        members = self.members
        all_card_num = len(all_card)
        player_cnt = len(members)
        dealer = self.room['dealer']
        self.room['dealer'] = ''
        player_card = []
        every_player_num = all_card_num/player_cnt
        for uid in members:
            player_card.append({"uid":uid, "left_num":every_player_num})
        
        user_card = {}
        for uid in members:
            user_card[uid] = []
        
        #上局赢家先冲牌
        first_rob = self.room['first_rob']
        if not first_rob:
            first_rob = dealer
            self.room['first_rob'] = first_rob
        
        self.room['first_call'] = first_rob
        for i in range(every_player_num):
            for uid in members:
                c = all_card.pop()
                #第一局红桃4先叫牌
                if game_round == 1 and c == 22:
                    self.room['first_call'] = uid
                user_card[uid].append(c)
        
        for uid in members:
            mid = self.incr_mid()
            player = Player(uid, self.bid, self.rid, True)
            card = user_card[uid]
            card.sort()
            card.reverse()
            player.current_card.clear()
            player.current_card.extend(card)
            card_list = [str(x) for x in card]
            nsq_pub({"b":self.bid, "u":str(uid), "t":"game", "d":{"act":"game_start", "status":"start", "rid":self.rid, "mid":mid, "dealer":"", "card":card_list, "game_round":self.room['game_round'], "all_round":self.room['all_round'], "player_card":player_card}})
        
        self.room['last_put_user'] = ''
        self.room['last_put_card'] = ''
        self.room['last_put_type'] = ''
        self.room['last_put_point'] = ''
        self.room['stop_pop_user'] = first_rob
        
        self.current_card.clear()
        logging.info(u"房间rid:%s,game_round:%s,发牌结束,通知%s抢庄" % (self.rid, self.room['game_round'], first_rob))
        self.notify_turn_rob(first_rob)

    def notify_turn_rob(self, uid):
        #通知玩家抢庄
        self.room['stop_pop_act'] = 'turn_rob'
        self.room['stop_pop_user'] = uid
        #self.tips_user.clear()
        #self.tips_user.extend(self.members)
        for member in self.members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"turn_rob", "uid":uid, "rid":self.rid}})

    def cancel_rob(self, uid, data={}):
        #不抢
        if uid != self.room['stop_pop_user']:
            return
        user_seat = self.members.index(uid)
        next_seat = (user_seat + 1) % self.members
        next_user = self.members[next_seat]
        first_rob = self.room['first_rob']
        for member in self.members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"cancel_rob", "uid":uid, "rid":self.rid}})
            
        if next_user == first_rob:
            first_call = self.room['first_call']
            self.notify_turn_call(first_call, 'y')
        else:
            self.notify_turn_rob(next_user)
            
    def rob(self, uid, data={}):
        if uid != self.room['stop_pop_user']:
            return
        
        self.room['call_score'] = 5
        for member in self.members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"rob", "uid":uid, "rid":self.rid}})
        
        self.room['stop_pop_act'] = ''
        self.pub_dealer(uid)

    def pub_dealer(self, dealer, dealer_win=False):
        self.room['dealer'] = dealer
        for member in self.members:
            member_player = Player(member, self.bid, self.rid)
            if member == dealer:
                role = 'dealer'
                is_dealer = 'y'
            else:
                role = 'player'
                is_dealer = 'n'
            member_player.score['role'] = role
            member_player.score['is_dealer'] = is_dealer
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"pub_dealer", "dealer":dealer, "rid":self.rid}})
        if not dealer_win:
            self.notify_keep_put(dealer)
        else:
            self.game_over(dealer)
        
    def notify_turn_call(self, uid, must_call='n'):
        #通知玩家招牌,叫牌
        self.room['stop_pop_act'] = 'turn_call'
        self.room['stop_pop_user'] = uid
        p = Player(uid, self.bid, self.rid)
        current_card = p.current_card.members
        all_card = self.crt_deck_card()
        for c in current_card:
            all_card.remove(c)
        
        game_mode = self.room['game_mode']
        if game_mode == 'k':
            all_card.remove(111)
            all_card.remove(112)
            all_card.remove(113)
            all_card.remove(114)
        else:
            all_card.remove(121)
            all_card.remove(122)
            all_card.remove(123)
            all_card.remove(124)
        valid_card = {}
        for c in all_card:
            d = str(int(c)/10)
            if d in valid_card:
                valid_card[d].append(c)
            else:
                valid_card[d] = [c]
        
        called_card = self.call_card.members
        for member in self.members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"turn_call", "must_call":must_call, "called_card":called_card,"valid_card":valid_card,"uid":uid, "rid":self.rid}})
            
    def cancel_call(self, uid, data={}):
        if uid != self.room['stop_pop_user']:
            return
        for member in self.members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"cancel_call", "uid":uid, "rid":self.rid}})
            
        user_seat = self.members.index(uid)
        next_seat = (user_seat + 1) % self.members
        next_user = self.members[next_seat]
        dealer = self.room['dealer']
        if next_user == dealer:
            self.pub_dealer(uid, dealer_win=True)
        else:
            self.notify_turn_call(next_user)
            
    def call_card(self, uid, data={}):
        #叫牌
        if uid != self.room['stop_pop_user']:
            return
        card = data['card']
        new_card = data['new_card']
        
        new_card_uid = ''
        p = Player(uid, self.bid, self.rid)
        current_card = p.current_card.members
        if new_card in current_card or card not in current_card:
            return
        if new_card in self.call_card:
            return
        
        for member in self.members:
            if member != uid:
                member_player = Player(member, self.bid, self.rid)
                member_card = member_player.current_card.members
                if new_card in member_card:
                    new_card_uid = member
                    break
        
        if not new_card_uid:
            return
        
        card_player = Player(new_card_uid, self.bid, self.rid)
        card_player.current_card.remove(new_card)
        card_player.current_card.append(card)
        p.current_card.append(new_card)
        p.current_card.remove(card)
        
        self.call_card.append(new_card)
        
        call_score = int(self.room['call_score'])
        call_score += 1
        self.room['call_score'] = call_score
        for member in self.members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"call_card", "uid":uid, "call_score":call_score,"new_card_uid":new_card_uid, "card":card,"new_card":new_card, "rid":self.rid}})
        
        user_seat = self.members.index(uid)
        next_seat = (user_seat + 1) % self.members
        next_user = self.members[next_seat]
        first_call = self.room['first_call']
        if next_user == first_call:
            self.pub_dealer(uid)
        else:
            self.notify_turn_call(next_user)
        
    def notify_keep_put(self, uid):
        self.room['stop_pop_user'] = uid
        self.room['last_put_user'] = ''
        self.room['last_put_card'] = ''
        self.room['last_put_type'] = ''
        self.room['last_put_point'] = ''
        members = self.members
        current_score = int(self.room['current_score'])
        player = Player(uid, self.bid, self.rid)
        if current_score > 0:
            player.score['card_score'] = int(player.score['card_score']) + current_score
            self.room['current_score'] = 0
            logging.info(u"玩家%s大牌,桌面分数%s,更新后分数%s" % (uid, current_score, player.score['card_score']))
            for member in members:
                nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"tips_score", "rid":self.rid, "uid":uid, "card_score":player.score['card_score']}})
        
        all_card = player.current_card.members
        if all_card:
            for member in members:
                if member == uid:
                    tips_list = []
                    card_type, card_num, card_point = self.get_card_type(all_card)
                    if card_type:
                        tips_list.append(all_card)
                    else:
                        current_card = sorted(all_card, key=lambda x:int(x))
                        card_list = {}
                        for c in current_card:
                            d = str(int(c)/10)
                            if d in card_list:
                                card_list[d].append(c)
                            else:
                                card_list[d] = [c]
                        tips_list = sorted(card_list.values(), key=lambda x:len(x)) 
                    valid_list = all_card
                else:
                    valid_list = []
                    tips_list = []
                nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"act":"turn_put", "put_type":"free", "uid":uid, "valid_list":valid_list, "rid":self.rid, "tips_list":tips_list, "last_put_card":[], "last_put_type":"", "last_put_point":[]}})
        else:
            self.notify_next_user(uid)
            
    def notify_next_user(self, pre_user, offline_user=None):
        members = self.members
        pre_user_seat = members.index(pre_user)
        next_user_seat = (pre_user_seat + 1) % len(members)
        next_user = members[next_user_seat]
        if not offline_user:
            self.room['stop_pop_user'] = next_user
        last_put_user = self.room['last_put_user']
        if not last_put_user or next_user == last_put_user:
            #首次出牌或者过一圈没人能打起
            self.notify_keep_put(next_user)
            return
        else:
            last_put_card = self.room['last_put_card'].split(",")
            last_put_type = self.room['last_put_type']
            last_put_point = self.room['last_put_point']
            if last_put_point:
                last_put_point = int(last_put_point)
            #判断下家能否打牌,没有打牌则自动发送要不起,否则发送出牌通知
            #last_put_type, last_put_point = self.get_card_type(last_put_card)
            p = Player(next_user, self.bid, self.rid)
            current_card = p.current_card.members
            logging.info(u"判断下家是否有牌:%s, last_put_card:%s, type:%s, point:%s" % (next_user, str(last_put_card), last_put_type, str(last_put_point)))
            valid_card = self.get_valid_card(current_card, last_put_card, last_put_type, last_put_point)
                    
            for member in members:
                if offline_user and member != offline_user:
                    continue
                if member == next_user:
                    valid_list, tips_list = valid_card
                    logging.info(u"下家%s可出的牌有:valid_list:%s, tips_list:%s" % (member, str(valid_list), str(tips_list)))
                    valid_list = sorted(valid_list, key=lambda x:int(x))
                    tips_list = sorted(tips_list, key=lambda x:len(x))
                    #logging.info(u"下家%s可出的牌有:%s" % (member, str(tips_list)))
                else: 
                    #logging.info(u"=============member:%s,next_user:%s" % (member, next_user))
                    valid_list, tips_list = [], []
                nsq_pub({"b":self.bid, "u":str(member), "t":"game", "d":{"act":"turn_put", "put_type":"follow", "uid":next_user, "rid":self.rid, "valid_list":valid_list, "tips_list":tips_list, "last_put_card":last_put_card, "last_put_type":last_put_type, "last_put_point":last_put_point}})
            
    
    def pass_card(self, uid, data={}):
        stop_pop_user = self.room['stop_pop_user']
        if uid != stop_pop_user:
            logging.error(u"pass,该%s打牌,不该%s" % (stop_pop_user, uid))
            get_last_data('', self.bid, uid, {"rid":self.rid})
            return
        members = self.members
        mid = self.incr_mid()
        for member in members:
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"pass", "mid":mid, "uid":uid, "rid":self.rid}})
        self.notify_next_user(uid)
        
    def put_card(self, uid, data):
        uid = str(uid)
        stop_pop_user = self.room['stop_pop_user']
        if uid != stop_pop_user:
            logging.error(u"该%s出牌,不该%s" % (stop_pop_user, uid))
            get_last_data('', self.bid, uid, {"rid":self.rid})
            return
        card = data['card']
        if not isinstance(card, list):
            card = card.split(",")
        card_type, card_num, card_point = self.get_card_type(card)
        logging.info(u"过炸检查用户牌型%s,%s" % (card_type, card_point))
        if not card_type:
            #牌型不符合
            logging.error(u"%s出牌不符合规范,%s" % (uid, ",".join(card)))
            get_last_data('', self.bid, uid, {"rid":self.rid})
            return 
        
        current_player = Player(uid, self.bid, self.rid)
        user_current_card = current_player.current_card.members
        for c in card:
            if c not in user_current_card:
                logging.error(u"出牌异常,用户%s没有该手牌,%s" % (uid, c))
                get_last_data('', self.bid, uid, {"rid":self.rid})
                return
        
        last_put_type = self.room['last_put_type']
        last_put_user = self.room['last_put_user']
        last_put_point = self.room['last_put_point']
        last_put_card = self.room['last_put_card']
        members = self.members
        if last_put_card:
            #跟上家的牌
            put_type = 'follow'
            card1 = last_put_card.split(",")
            if not self.compare_card(card1, card):
                logging.error(u"出牌异常,用户%s出牌牌不能大过上家,%s" % (uid, ",".join(card)))
                get_last_data('', self.bid, uid, {"rid":self.rid})
                return
        else:
            #自由出牌
            put_type = 'free'
        
        for c in card:
            current_player.current_card.remove(c, 1)
            current_player.out_card.append(c)
            #self.current_card.append(c)
        
        self.room['last_put_card'] = ",".join(card)
        self.room['last_put_type'] = card_type
        self.room['last_put_point'] = card_point
        self.room['last_put_user'] = uid
        user_left_card = current_player.current_card.members
        left_num = len(user_left_card)
        mid = self.incr_mid()
        for member in members:
            if member == str(uid):
                left_card = user_left_card
            else:
                left_card = []
                
            nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"put_card", "mid":mid, "put_type":put_type, "left_card":left_card, "left_num":left_num, "uid":uid, "rid":self.rid, "card":card, "card_type":card_type}})
        
        if user_left_card:
            if left_num <= 1:
                for member in members:
                    nsq_pub({"b":self.bid, "u":member, "t":"game", "d":{"act":"card_warning", "left_num":left_num, "uid":uid, "rid":self.rid}})
            self.notify_next_user(uid)
        else:
            self.game_over(uid)
    
                
    def game_over(self, winner='', from_dissmiss=False, duty_uid=''):
        dealer = self.room['dealer']
        self.room['status'] = 'over'
        db = dao.Game_DB()
        rules = {}
        gid = self.room['gid']
        if gid:
            rows = db.game_rule(gid)
        else:
            rows = db.room_rule(self.rid)
            gid = ""
        for row in rows:
            k = row['param']
            v = row['value']
            rules[k] = v
        game_round = self.room['game_round']
        if game_round:
            game_round = int(game_round)
        else:
            game_round = 1
            
        all_round = self.room['all_round']
        if all_round:
            all_round = int(all_round)
        else:
            all_round = 1
        if winner == dealer:
            dealer_win = True
        else:
            dealer_win = False
        win_score = 0
        if winner:
            next_dealer = winner
            for member in self.members:
                member_player = Player(member, self.bid, self.rid)
                card_score = int(member_player.score['final_card_score']) - 150
                user_prize = int(member_player.score['user_prize'])
                final_score = card_score/10 + user_prize*2
                member_player.score['score'] = final_score
                
                db.update_player(self.rid, member, final_score, 0)
                db.commit()
                
            base_score = int(self.room['call_score'])
            if dealer_win:
                #庄家赢
                for member in self.members:
                    p = Player(member, self.bid, self.rid)
                    if member != dealer:
                        win_score = -base_score
                    else:
                        win_score = base_score * 2
                    p.score['score'] = win_score
                    db.update_player(self.rid, member, win_score, 0)
                    db.commit()
            else:
                for member in self.members:
                    p = Player(member, self.bid, self.rid)
                    if member != dealer:
                        win_score = base_score
                    else:
                        win_score = -base_score * 2
                    p.score['score'] = win_score
                    db.update_player(self.rid, member, win_score, 0)
                    db.commit()
        else:
            next_dealer = dealer
        
        player_card = []
        for member in self.members:
            member_player = Player(member, self.bid, self.rid)
            user_data = member_player.get_data()
            player_info = db.get_player(self.rid, member)
            user_data['user_score'] = player_info['score']
            score = user_data['score']
            player_card.append(user_data)
            if int(score) >0:
                is_win = 1
            else:
                is_win = 0
            db.add_room_log(0, 0, self.rid, game_round, member, score, 0, 0, user_data['is_dealer'], is_win, 0, '')
            db.commit()
        room_over = 'n'
        if from_dissmiss or game_round >= all_round:
            room_over = 'y'
        db.game_over(self.rid, game_round)
        db.commit()
        mid = self.incr_mid()
        self.room['dealer'] = next_dealer
        self.room['game_round'] = game_round + 1
        game_type = self.room['game_type']
        for member in self.members:
            pub_data = {"b":self.bid, "u":member, "t":"game", "d":{"mid":mid, "act":"game_over", "room_over":room_over, "game_type":game_type, "dealer":dealer, "player_card":player_card, "game_round":game_round, "rid":self.rid,}}
            nsq_pub(pub_data)
            #db.save_game_over(self.rid, game_round, "game_over", member, urllib.quote(json_encode(pub_data).encode("utf-8")))
            #db.commit()
        if room_over == 'y':
            self.dismiss()
        
    def dismiss(self, act='room_over'):
        db = dao.Game_DB()
        player_stat = []
        player_data = {}
        p_stat = db.player_stat(self.rid)
        if p_stat:
            winner = p_stat[-1]['uid']
            max_score = p_stat[-1]['score']
            for ps in p_stat:
                tmp = {}
                tmp['uid'] = ps['uid']
                tmp['score'] = int(ps['score'])
                tmp['win_num'] = int(ps['win_num'])
                tmp['max_score'] = int(ps['max_score'])
                tmp['lose_num'] = int(ps['lose_num'])
                if ps['score'] == max_score:
                    is_winner = 'y'
                else:
                    is_winner = 'n'
                tmp['is_winner'] = is_winner
                player_stat.append(tmp)
                player_data[str(ps['uid'])] = tmp
        else:
            winner = ""
            for uid in self.members:
                player_stat.append({"uid":uid, "score":"0","max_score":"0","lose_num":"0","win_num":"0"})
                
        room_info = db.get_room(self.rid, self.bid)
        admin = room_info['admin']
        #gid = room_info['gid']
        #if not gid:
        #    gid = 0
        #for ps in player_stat:
        #    if ps['uid'] == winner:
        #        is_winner = 'y'
        #    else:
        #        is_winner = 'n'
        #    db.add_room_stat(match_id, gid, self.rid, ps['uid'], ps['score'], is_winner)
        #    db.commit()
        for uid in self.members:
            if not uid:
                continue
            pub_data = {"b":self.bid, "u":str(uid), "t":"game", "d":{"act":"room_over", "rid":self.rid, "player_stat":player_stat, "winner":winner, "admin":admin}}
            #db.save_game_over(self.rid, 0, "room_over", uid, json_encode(pub_data))
            #db.commit()
            nsq_pub(pub_data)
        db.dismiss_room(self.rid)
        db.commit()
        for member in self.members:
            member_player = Player(member, self.bid, self.rid)
            member_player.clear()
        redisco.connection.delete("r:%s:current_card" % self.rid)
        redisco.connection.delete("r:%s:out_card" % self.rid)
        redisco.connection.delete("r:%s" % self.rid)
        redisco.connection.delete("r:%s:mid" % self.rid)
        redisco.connection.delete("r:%s:p" % self.rid)
    
